# encoding: utf-8
"""
    IM客户端
"""
import socket, msgpack, time
from convert import convert, ia_configure
import threading, qasql
__author__ = 'jiaoshupeng'


class clientIM():
    def __init__(self, username, password):
        # 设置聊天host和port
        self.chart_host = ia_configure.url_chat
        self.chat_port = 8080
        self.classCon = convert(username, password)
        self.address = (self.chart_host, self.chat_port)

    def socketIM(self):
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            remote_ip = socket.gethostbyname(self.chart_host)
            self.sock.connect((remote_ip, self.chat_port))
        except:
            print '连接失败'
        try:
            sendData = bytearray(self.classCon.getStart())
            # 定义鉴权包
            self.sock.send(sendData)
            # 发送鉴权包
            reply =self.sock.recv(16)
            getHeader = self.headerByte(reply)
            # 获取鉴权头
            if getHeader == '00010010': # 判断鉴权是否成功
                print '鉴权成功'
                threads = []
                # 发送消息
                sendMsg = threading.Thread(target=self.sendMsg,args=())
                threads.append(sendMsg)
                # 接收消息
                # 后期需要释放------------************------------
                # recMsg = threading.Thread(target=self.recMsg,args=())
                # threads.append(recMsg)

                for thread in threads:
                    thread.setDaemon(True)
                    thread.start()
                thread.join()
            else:
                print '连接断开'
                return False
        finally:
            self.sock.close()

    def headerByte(self, reply):  # 解析头部
        getReply = bytearray(reply)
        head = bin(getReply[0]).replace('0b', '').zfill(8)
        return head

    def pingByte(self, reply):
        header = bin(reply[0]).replace('0b', '').zfill(8)
        if header == '00101001':  # 心跳包只包含头
            try:
                dataByte = []
                for num in range(8):
                    data = bin(reply[num]).replace('0b', '').zfill(8)
                    dataByte.append(data)
                version = self.montage(dataByte[1])
                messageLen = self.montage(dataByte[2:6])
                pingTime = self.montage(dataByte[6:8])
                result = '接收到服务器发送的心跳包,心跳包版本为%d,消息体长度为%d,间隔时间为%d秒'%(version, messageLen, pingTime)
            except:
                result = '接收到服务器发送的心跳包,心跳包仅包含header'
        elif header == '00111010':  # 消息送达成功
            arrMsg = []
            for num in range(0, 23):
                dataMsg = bin(reply[num]).replace('0b','').zfill(8)
                arrMsg.append(dataMsg)
            header = arrMsg[0]
            version = int(arrMsg[1], 2)
            msgLenth = int(''.join(arrMsg[2:6]), 2)
            res = int(arrMsg[6], 2)
            localId = int(''.join(arrMsg[7:11]), 2)
            if res == 0:
                result = '消息成功送达,header为%s, 版本为%s, 消息长度为%s, local ID为%s'%(header, version, msgLenth, localId)
                time.sleep(3)
                self.sock.close()
            else:
                result = '消息送达失败, header为%s, 版本为%s, 消息长度为%s'%(header, version, msgLenth)
        elif header == '01001000':
            if len(reply) == 20:
                result = '您的消息已被对方查看'
            else:
                arrMsg = []
                for num in range(0, len(reply)):
                    dataMsg = bin(reply[num]).replace('0b','').zfill(8)
                    arrMsg.append(dataMsg)
                binMsg = ''.join(arrMsg[28:])
                strMsg = msgpack.unpackb(convert().restore(binMsg))
                name = strMsg['profile']['name']
                contents = strMsg['contents']
                result = '用户  %s  给您发来新消息,消息内容为:  %s'%(name, contents)
        elif header == '00100001':
            result = '接收到服务器不带有payloads PING'
            pingData = bytearray(self.classCon.ping(1))
            self.sock.send(pingData)
        else:
            print header
            result = '服务器断开连接'
        return result

    def montage(self, values):
        if type(values) == str:
            result = values
        else:
            result = ''.join(values)
        res = int(result, 2)
        return res

    def sendMsg(self):
        num = 0
        while True:
            # guestUid = raw_input("请输入对方的uid:\n")
            # msgContents = raw_input('请输入您要发送的文字:\n')
            guestUid = '9334494'
            msgContents = '你好'
            msgData = bytearray(self.classCon.sendWord(int(guestUid), msgContents))
            self.sock.send(msgData)
            num += 1
            if num == 1:
                break

    def recMsg(self):
        while True:
            try:
                ping = self.sock.recv(1024)
                getPing = bytearray(ping)
                header = bin(getPing[0]).replace('0b', '').zfill(8)
                if header == '00101001':
                    print self.pingByte(getPing)
                    pingData = bytearray(self.classCon.ping(1))
                    self.sock.send(pingData)
                else:
                    print self.pingByte(getPing)
            except:
                print '程序出错'
                break

if __name__ == '__main__':
    user = qasql.sel(10)
    for user_data in user:
        username = user_data[0]
        password = user_data[1]
        a = clientIM(username, password)
        a.socketIM()